﻿using ICSharpCode.AvalonEdit.Folding;
using ICSharpCode.AvalonEdit;
using System.Text;
using System.Windows;
using WpfMqttAnalyzeApp.Model;
using System.Windows.Threading;
using ReactiveUI;
using WpfMqttAnalyzeApp.Services;
using System.Reactive;
using System.Security.Cryptography;
using MqttAnalyze.Data.Models;
using MqttAnalyze.App.Wpf.PopWindows;
using System.IO;
using MqttAnalyze.Data.Common;
using System.Reactive.Linq;
using System.Windows.Controls;
using System.Windows.Interop;

namespace WpfMqttAnalyzeApp
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window, IViewFor<MainMqttVm>
    {
        FoldingManager sendMsgCheckManager;
        FoldingManager recvMsgCheckManager;
        DispatcherTimer foldingUpdateTimer;
        MqttMsgService mqttCls;
        public MainMqttVm ViewModel { get; set; }
        public MainWindow()
        {
            InitializeComponent();
            mqttCls = new MqttMsgService();
            var userData=new UserData();
            try
            {
                var jsonStr = File.ReadAllText(Path.Combine(AppContext.BaseDirectory, "userData.json"));
                var jsonObject= Newtonsoft.Json.JsonConvert.DeserializeObject<UserData>(jsonStr);
                if (jsonObject != null)
                {
                    userData = jsonObject;
                }
            }
            catch (Exception ex)
            {
                LogHelper.Error(ex,"<Read Json data>");
            }
            DoReactiveBinding(userData);
            
            //控件逻辑
            aeRecvContent.TextArea.IndentationStrategy = new ICSharpCode.AvalonEdit.Indentation.DefaultIndentationStrategy();
            recvMsgCheckManager = FoldingManager.Install(aeRecvContent.TextArea);
            aeSendContent.TextArea.IndentationStrategy = new ICSharpCode.AvalonEdit.Indentation.DefaultIndentationStrategy();
            sendMsgCheckManager = FoldingManager.Install(aeSendContent.TextArea);

            foldingUpdateTimer = new DispatcherTimer();
            foldingUpdateTimer.Interval = TimeSpan.FromSeconds(2);
            foldingUpdateTimer.Tick += delegate { UpdateFoldings(); };
            foldingUpdateTimer.Start();
        }

        object IViewFor.ViewModel
        {
            get => ViewModel;
            set => ViewModel = (MainMqttVm)value;
        }

        private void DoReactiveBinding(UserData data)
        {
            //Todo 如何转圈圈
            this.WhenActivated(a =>
            {
                a(this.WhenAnyValue(x => x.ViewModel).BindTo(this, x => x.DataContext));
                a(this.Bind(ViewModel, vm => vm.MqttAddr, v => v.tbMqttAddr.Text));
                a(this.Bind(ViewModel, vm => vm.SendTopic, v => v.tbSendTopic.Text));
                a(this.OneWayBind(ViewModel, vm => vm.QosList, v => v.cmbQos.ItemsSource));
                a(this.OneWayBind(ViewModel, vm => vm.ListenTopics, v => v.classifyTree.ItemsSource));
                a(this.OneWayBind(ViewModel, vm => vm.MsgTemplates, v => v.templateList.ItemsSource));
                a(this.Bind(ViewModel, vm => vm.QosIndex, v => v.cmbQos.SelectedIndex));
                a(this.Bind(ViewModel, vm => vm.RecvTopic, v => v.tbReceiveTopic.Text));
                a(this.Bind(ViewModel, vm => vm.Classify, v => v.tbCategoryKey.Text));
                a(this.Bind(ViewModel, vm => vm.KeepNum, v => v.tbAmount.Text));
                a(this.Bind(ViewModel, vm => vm.IsRetain, v => v.ckbRetain.IsChecked));
                a(this.Bind(ViewModel, vm=>vm.IsLoading, v=>v.loadingMask.IsActive));
                a(this.BindCommand(ViewModel, vm => vm.CleanContentCmd, x => x.btnClearSend, "Click"));
                a(this.BindCommand(ViewModel, vm => vm.CleanContentCmd, x => x.btnClearRecv, "Click"));
                a(this.BindCommand(ViewModel, vm => vm.ButtonConnectCmd, x => x.btnConect, "Click"));
                a(this.BindCommand(ViewModel, vm => vm.MqttSubscribeCmd, x => x.btnSubscribe, "Click"));   
                //a(this.BindCommand(ViewModel, vm => vm.MqttUnsubscribeCmd, x => x.btnRemoveTopic, "Click"));
               
                // a(this.BindCommand(ViewModel, vm => vm.MqttSendCmd, x => x.btnSend, "Click"));

                a(this.BindInteraction(ViewModel, vm => vm.ClickRst, interaction =>
                {
                    ViewModel.IsLoading = false;
                    var rst = interaction.Input;
                    if (rst.RtnCode != 0)
                    {
                        MessageBox.Show("操作失败");
                        interaction.SetOutput(Unit.Default);
                        return Task.CompletedTask;
                    }
                    DoSuccessResult(rst);
                    interaction.SetOutput(Unit.Default);
                    return Task.CompletedTask;
                }));

                a(this.BindInteraction(ViewModel, vm => vm.RecvMsgRst, interaction =>
                {
                    var rst = interaction.Input;
                    DoRecvResult(rst);
                    interaction.SetOutput(Unit.Default);
                    return Task.CompletedTask;
                }));

                a(this.BindInteraction(ViewModel, vm => vm.SelectTopicMsgRst, interaction =>
                {
                    var rst = interaction.Input;
                    ShowRecvMsgResult(rst);
                    interaction.SetOutput(Unit.Default);
                    return Task.CompletedTask;
                }));
            });
            ViewModel = new MainMqttVm(mqttCls, data);

        }

        private void UpdateFoldings()
        {
            var bFlod = new JsonBraceFoldingStrategy();
            if (recvMsgCheckManager != null)
            {
                bFlod.UpdateFoldings(recvMsgCheckManager, aeRecvContent.Document);
            }
            if (sendMsgCheckManager != null)
            {
                bFlod.UpdateFoldings(sendMsgCheckManager, aeSendContent.Document);
            }
        }

        private void DoSuccessResult(OperateResult rst)
        {
            switch (rst.Operation)
            {
                case EOperationType.ClearContent:
                    {
                        if (ViewModel.PanelIndex == 1)
                        {
                            this.Dispatcher.BeginInvoke(new Action(() =>
                            {
                                aeSendContent.Document.Text = string.Empty;
                            }));
                        }
                        else
                        {
                            this.Dispatcher.BeginInvoke(new Action(() =>
                            {
                                ViewModel.UpdateTopicCount();
                                aeRecvContent.Document.Text = string.Empty;
                            }));
                        }
                        break;
                    }
                case EOperationType.Connect:
                case EOperationType.Disconnect:
                    {
                        if (ViewModel.IsMqttConnect)
                        {
                            btnConect.Content = "断开";
                            ViewModel.RefreshTplCmd.Execute();
                            ViewModel.RefreshTopicCmd.Execute();
                        }
                        else
                        {
                            btnConect.Content = "连接";
                        }
                        break;
                    }
                case EOperationType.AddTemplate:
                case EOperationType.SaveTemplate:
                case EOperationType.RemoveTemplate:
                    {
                        ViewModel.RefreshTplCmd.Execute();
                        break;
                    }
                case EOperationType.Subscribe:
                    {
                        ViewModel.RefreshTopicCmd.Execute();
                        break;
                    }
                case EOperationType.Unsubscribe:
                    {
                        this.Dispatcher.BeginInvoke(new Action(() =>
                        {
                            string topic = (string)rst.RtnData;
                            var delItem=ViewModel.ListenTopics.FirstOrDefault(t => t.Topic == topic);
                            if(delItem!=null)
                            {
                                ViewModel.ListenTopics.Remove(delItem);
                            }
                            aeRecvContent.Document.Text=string.Empty;
                        }));
                        break;
                    }
            }
        }

        private void DoRecvResult(OperateResult rst)
        {
            if (rst.Operation == EOperationType.ReceiveMsg)
            {
                var msg = rst.RtnData as RecvMessage;
                if (msg != null)
                {
                    this.Dispatcher.BeginInvoke(new Action(() =>
                    {
                        // 更新ListenTopics的TotalNum
                        ViewModel.UpdateRecvMsgCount(msg);
                        if ((msg.SubClass == ViewModel.CurrentSubClass || ViewModel.CurrentSubClass==string.Empty) && msg.Topic == ViewModel.CurrentRecvTopic)
                        {
                            aeRecvContent.AppendText(msg.RecvTime + "\r\n");
                            aeRecvContent.AppendText(msg.Content + "\r\n\r\n");
                        }
                    }));

                }
            }
        }

        private void ShowRecvMsgResult(OperateResult rst)
        {
            if (rst.Operation == EOperationType.OpenCategory)
            {
                var msgList = rst.RtnData as List<MqttMessage>;
                if (msgList != null)
                {
                    this.Dispatcher.BeginInvoke(new Action(() =>
                    {
                        aeRecvContent.Document.Text = string.Empty;
                        foreach (var msg in msgList)
                        {
                            aeRecvContent.AppendText(msg.RecvTime + "\r\n");
                            aeRecvContent.AppendText(msg.Content + "\r\n\r\n");
                        }
                    }));
                }
            }
        }

        private void BtnClick_Send(object sender, RoutedEventArgs e)
        {
            //编辑区的内容不能绑定, 需要用传参方法传递
            var param = new SendCmdParam()
            {
                IsRetain = ckbRetain.IsChecked == true,
                Message = aeSendContent.Text,
                Topic = tbSendTopic.Text,
                Qos = cmbQos.SelectedIndex
            };
            ViewModel.MqttSendCmd.Execute(param);
        }

        private void BtnClick_SaveTpl(object sender, RoutedEventArgs e)
        {
            if(string.IsNullOrEmpty(tbSendTopic.Text))
            {
                var confirmRst = MessageBox.Show(this, "Topic主题不能为空", "提示", MessageBoxButton.OK);
                return;
            }
            var nameWin = new SaveNameWindow();
            nameWin.Owner = this;
            if (nameWin.ShowDialog() == true)
            {
                var param = new SaveMsgTemplate()
                {
                    TemplateName = nameWin.GetName(),
                    IsRetain = ckbRetain.IsChecked == true,
                    Message = aeSendContent.Text,
                    Topic = tbSendTopic.Text,
                    Qos = cmbQos.SelectedIndex
                };
                ViewModel.SaveTemplateCmd.Execute(param);
            }
        }


        private void TopicTreeView_PreviewMouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            TopicTreeListener caseData = null;
            if (e.OriginalSource is Border bd)
            {
                caseData = bd.DataContext as TopicTreeListener;
            }
            else if (e.OriginalSource is TextBlock tb)
            {
                caseData = tb.DataContext as TopicTreeListener;
            }
            else if (e.OriginalSource is System.Windows.Documents.Run rn)
            {
                caseData = rn.DataContext as TopicTreeListener;
            }
            if (caseData != null)
            {
                string topic=caseData.Topic;
                string subClass = string.Empty;
                if(caseData.IsLeaf==true)
                {
                    subClass = caseData.NodeName;
                    if(subClass.StartsWith("(Default"))
                    {
                        subClass = string.Empty;
                    }
                }
                else
                {
                    ViewModel.ShowTopicCategory(topic);
                }
                ViewModel.SetCurrentCategory(topic, subClass);
            }
            else
            {
                if (!(e.OriginalSource is Border))
                {
                    e.Handled = true;
                }
            }
        }

        private void TopicTreeView_PreviewMouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            e.Handled = true;
        }

        private void BtnClick_SelectTpl(object sender, RoutedEventArgs e)
        {
            var btn = sender as Button;
            var item = btn.DataContext as MsgTemplate;
            if (item != null)
            {
                ViewModel.ShowTemplateData(item);
                aeSendContent.Text = item.Message;
            }
        }

        private void BtnClick_RemoveTpl(object sender, RoutedEventArgs e)
        {
            var btn = sender as Button;
            var item = btn.DataContext as MsgTemplate;
            var confirmRst = MessageBox.Show(this,"确定删除模板?","提示",MessageBoxButton.OKCancel);
            if (confirmRst == MessageBoxResult.OK)
            {
                var param = new SaveMsgTemplate()
                {
                    TemplateId= item.TemplateId
                };
                ViewModel.DeleteTplCmd.Execute(param);
            }
        }

        private void BtnClick_RemoveTopic(object sender, RoutedEventArgs e)
        {
            var btn = sender as MenuItem;
            var item = btn.DataContext as TopicTreeListener;
            var confirmRst = MessageBox.Show(this, $"确定取消订阅[{item.Topic}]?", "提示", MessageBoxButton.OKCancel);
            if (confirmRst == MessageBoxResult.OK)
            {
                var param = new SaveMsgTemplate()
                {
                   Topic= item.Topic
                };
                ViewModel.MqttUnsubscribeCmd.Execute(param);
            }
        }

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            var confirmRst = MessageBox.Show(this, "确认关闭软件?", "提示", MessageBoxButton.OKCancel);
            if (confirmRst != MessageBoxResult.OK)
            {
                e.Cancel = true;
                return;
            }
        }
    }
}